package com.behelpful.common.core.jackson;

import com.behelpful.common.core.enums.IEnum;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.springframework.beans.BeanUtils;

import java.io.IOException;

/**
 * 枚举反系列化规则自定义：支持客户端传参：枚举code 或 枚举name 或 枚举对象（取枚举对象的name）
 *
 * @author Alay
 * @date 2021-08-17 09:47
 * @project be-helpful
 * @since
 */
public class IEnumDeserializer extends JsonDeserializer<IEnum> {

    @Override
    public IEnum deserialize(JsonParser jp, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        String currentName = jp.currentName();
        Object currentValue = jp.getCurrentValue();
        @SuppressWarnings("rawtypes")
        Class enumClazz = BeanUtils.findPropertyType(currentName, currentValue.getClass());

        IEnum iEnum;
        if (node instanceof IntNode) {
            // 当客户端传值为枚举的 code 的值得时候
            iEnum = (IEnum) IEnum.codeOf(enumClazz, node.asInt());
        } else if (node instanceof TextNode) {
            // 当客户端传值为 枚举的 name 时候
            iEnum = (IEnum) IEnum.sourceOf(enumClazz, node.asText());
        } else {
            // 若传参的是枚举对象时, JsonNode 为 ObjectNode 类,枚举对象的数据放在一个 LinkedHashMap 中,只需要从 Map 中读取出 name 即可
            iEnum = (IEnum) IEnum.sourceOf(enumClazz, node.get("name").asText());
        }
        return iEnum;
    }

    // JsonFormat annotation = (JsonFormat) enumClazz.getAnnotation(JsonFormat.class);

        /*if (annotation == null || annotation.shape() != JsonFormat.Shape.OBJECT) {
            // 当客户端传值为枚举的 name 的时候,而且枚举上没有加入 @JsonFormat(shape = JsonFormat.Shape.OBJECT)
            iEnum = (IEnum) IEnum.sourceOf(enumClazz, node.asText());
        } else
         */
}
